#ifndef COUPLINGUTILS_H
#define COUPLINGUTILS_H

#include <string>
#include <vector>

namespace NApiEDEM
{

/*
* The following is provided to help with the new functionality associated with the
* Coupling Interface's deformable geometry offering. Part of the process of inserting
* a geometry, without the need for any thrid party software, is to specify NODE and
* ELEMENT collections that define the geometry. This helper class should 'simplify'
* that part of the geometry definition process
*/

/**
 * Use this class for defining the NODE and ELEMENT list associated with the geometry
 *
 */
template <class T>
class CInsertGeometryHelper
{
public:
    CInsertGeometryHelper() : m_id(), m_x(), m_y(), m_z() {}
    CInsertGeometryHelper(unsigned int id, T x, T y, T z) { m_id = id; m_x = x; m_y = y; m_z = z; }

    inline unsigned int id() const { return m_id; }
    inline T x() const { return m_x; }
    inline T y() const { return m_y; }
    inline T z() const { return m_z; }

    inline void setId(unsigned int id) { m_id = id; }
    inline void setX(T x) { m_x = x; }
    inline void setY(T y) { m_y = y; }
    inline void setZ(T z) { m_z = z; }

private:
    unsigned int m_id;

    T m_x;
    T m_y;
    T m_z;
};

/**
 * This class helps with definition of the geometry's sections, using a subset of 
 * the elements for definition of the triangle set.
 *
 */
class CGeometrySection
{
public:
    CGeometrySection() : m_groupId(1), m_elementCount(0), m_solidSection(true),
                            m_sectionName {}, m_triangles {}
    {}

    CGeometrySection(unsigned int groupId, unsigned int elementCount, bool isSolid, std::string sectionName,
                        std::vector<unsigned int> triangles = std::vector<unsigned int>()):
        m_groupId(groupId),
        m_elementCount(elementCount),
        m_solidSection(isSolid),
        m_sectionName(sectionName),
        m_triangles(triangles)
    {}

    inline unsigned int getId() const { return m_groupId; }
    inline unsigned int getElementCount() const { return m_elementCount; }
    inline bool getIsSolid() const { return m_solidSection; }
    inline const std::string& getName() const { return m_sectionName; }
    inline const std::vector<unsigned int>& getTriangles() const { return m_triangles; }

    inline void setId(unsigned int id) { m_groupId = id; }
    inline void setElementCount(unsigned int elCount) { m_elementCount = elCount; }
    inline void setElements(std::vector<unsigned int> elements) { m_triangles = elements; }
    inline void addElement(unsigned int element) { m_triangles.push_back(element); }
    inline void setIsSolid(bool isSolid) { m_solidSection = isSolid; }
    inline void setName(const std::string& name) { m_sectionName = name; }

private:
    unsigned int m_groupId;
    unsigned int m_elementCount;
    bool m_solidSection;
    std::string m_sectionName;
    std::vector<unsigned int> m_triangles;
};

//Used for some convenience in the geometry related coupling methods
enum class ELocalOrGlobal { LOCAL, GLOBAL };
//Used for some convenience in the geometry related coupling methods. 
enum class ESetOrOffset { DIRECT_SET, OFFSET };
}

#endif // COUPLINGUTILS_H